﻿if (!AMap.Hotspot) {
    AMap.Hotspot = function (mapObj, mapTypeObj, debug) {
        this.mapObj = mapObj;
        this.hotspots = {};
        this.debug = debug || false;
        this.marker = null;
        this.markerListener = null;
        this.tipsMarker = null;
        this.allowedZooms = [10, 18];
        this.lastTileId = "";
        this.serviceURL = "http://mapclick.amap.com/poi/poi?tiles=";
        this.lastPOI = null;
        this.eventListeners = [];
        this.mapTypeObj = mapTypeObj || null;
        this.mapTypeDefaultOptions = {};
        this.initialize();
    };
    AMap.Hotspot.prototype = {
        constructor: AMap.Hotspot,
        requestNewTilesData: function (tiles) {
            return $.ajax({ url: this.serviceURL + tiles.join(";") + "&level=" + this.mapObj.getZoom(), type: "GET", dataType: "jsonp", jsonp: "cbk", async: !1, cache: !1 });
        },
        _handleMapMove: function () {
            var that = this, mapObj = this.mapObj;
            var newTiles = that.getNewTiles(), currentZoom = mapObj.getZoom();
            if (newTiles.length > 0 && currentZoom >= that.allowedZooms[0] && currentZoom <= that.allowedZooms[1]) {
                that.requestNewTilesData(newTiles).then(function (data, textStatus, jqXHR) {
                    that.addHotspot(data); if (that.debug) { console.log("hotspots:"); console.log(that.hotspots); }
                }, function (jqXHR, textStatus, errorThrown) { if (that.debug) debugger; });
            }
        },
        _handleMouseMove: function (evt) {
            var that = this, mapObj = that.mapObj;
            var isPromptShow = false;
            var pixelLoc = mapObj.lnglatToPixel(evt.lnglat, mapObj.getZoom()),
                tile_x = Math.floor(pixelLoc.x / 256),
                tile_y = Math.floor(pixelLoc.y / 256),
                currentTile = that.hotspots[tile_x + "," + tile_y];
            if (!currentTile) return false;
            //if (that.debug) { console.log("current tile exits:", currentTile); }
            for (var i = 0, l = currentTile.length; i < l; i++) { // loop up all POIs in the current tile
                var currentPOI = currentTile[i];
                var bound = currentPOI.b;
                var thisId = tile_x + '-' + tile_y + '-' + currentTile[i].d;
                if (evt.lnglat.lng > bound[0] && evt.lnglat.lng < bound[2] && evt.lnglat.lat > bound[1] && evt.lnglat.lat < bound[3]) {
                    if (that.debug) { console.log("In range,thisId:", thisId); }
                    isPromptShow = true;
                    if (that.lastTileId != thisId) {
                        if (that.debug) { console.log("currentTile[i]", currentPOI, i); console.log('evt:', evt); console.log('lastId', that.lastTileId); console.log('thisId', thisId); }
                        that.showMarker(mapObj, currentPOI);
                        that.lastTileId = thisId;
                        that.lastPOI = currentPOI;
                    }
                    break;
                }   
            }
            if (isPromptShow) {
                if (that.tipsMarker && that.tipsMarker.poiName && that.tipsMarker.poiName == currentPOI.n) {
                    return;
                }
                that.showPrompt(currentPOI, evt.lnglat);
            } else {
                that.removePrompt();
            }
        },
        _handleZoomChange: function () {
            var that = this;
            that._resetStatus();
            that._handleMapMove(); // Get all new POIs.
        },
        _resetStatus: function(){
            var that = this;
            that.hotspots = {}; // Clear all hot spots.
            if(that.marker) {
                that.marker.setMap(null); // Remove marker from map.
                that.marker = null; // unset the marker object.
                AMap.event.removeListener(that.markerListener);
                that.markerListener = null;
            }
            if(that.tipsMarker){
                that.tipsMarker.setMap(null); // Remove marker from map.
                that.tipsMarker = null; // unset the marker object.
            }
            that.lastTileId = "";
            that.lastPOI = null;
        },
        initialize: function () {
            var mapObj = this.mapObj;
            var that = this;
            var currentTiles = mapObj.getTiles(), currentZoom = mapObj.getZoom();
            that.addPrompt();
            that.addMarker();
            if (currentZoom >= that.allowedZooms[0] && currentZoom <= that.allowedZooms[1]) {
                that.requestNewTilesData(currentTiles).then(function (data, textStatus, jqXHR) {
                    that.addHotspot(data);
                }, function (jqXHR, textStatus, errorThrown) {
                    if (that.debug) debugger;
                });
            }
            // remember the AMap.MapType options.
            if (that.mapTypeObj) {
                that.mapTypeDefaultOptions = {
                    defaultType: that.mapTypeObj.defaultType,
                    showTraffic: that.mapTypeObj.showTraffic,
                    showRoad: that.mapTypeObj.showRoad
                };
                // If the default type is 1, set showRoad to true
                if (that.mapTypeObj.defaultType === 1 && !that.mapTypeObj.showRoad) {
                    var mapType = new AMap.MapType({
                        defaultType: 1,
                        showRoad: true,
                        showTraffic: that.mapTypeObj.showTraffic
                    });
                    that.mapTypeObj = mapType; // TODO
                    that.mapObj.addControl(mapType);
                }
            }
            that.eventListeners.push(AMap.event.addListener(mapObj, "mousemove", this._handleMouseMove, that));
            that.eventListeners.push(AMap.event.addListener(mapObj, "dragend", this._handleMapMove, that));
            that.eventListeners.push(AMap.event.addListener(mapObj, "zoomchange", this._handleZoomChange, that));
        },
        removePrompt: function () {
            if (this.tipsMarker) {
                this.tipsMarker.poiName = null;
                this.tipsMarker.hide();
            }
        },
        showPrompt: function (poi, location) {
            var that = this;
            if (!that.tipsMarker) that.addPrompt();
            if (poi.n) {
                that.tipsMarker.setPosition(location);
                that.tipsMarker.setContent('<div style="position: relative; background-color: #FFFEEF; border: 1px solid #7E7E7E; margin:15px 0 0 15px; padding: 3px 8px 3px 7px; font-size: 12px; white-space: nowrap; background-position: initial initial; background-repeat: initial initial;"><div style="color: #7E7E7E;">' + poi.n + "</div></div>");
                that.tipsMarker.poiName = poi.n;
                that.tipsMarker.show();
            }
        },
        addPrompt: function () {
            var that = this;
            if (that.tipsMarker) return ;
            that.tipsMarker = new AMap.Marker({
                position: that.mapObj.getCenter(),
                map: that.mapObj,
                zIndex: 99998,
                content: '',
                visible: false,
            });
        },
        showMarker: function (mapObj, poi) {
            var that = this;
            var j = [], k = this.debug ? "border:#F00 solid 1px;" : "";
            if (poi.i) { // First background marker
                j.push("<div class='hotspots' style=\"" + k + "left:" + poi.i[0] + "px;top:" + poi.i[1] + "px;width:" + poi.i[2] + "px;height:" + poi.i[3] + "px;");
                if (AMap.Util.isIE && !AMap.Util.isIE9) {
                    j.push("background-color:#fff;cursor:hand;filter:alpha(opacity=1);");
                    if (10 === document.documentMode) { j.push("opacity:0.01;"); }
                }
                j.push('position:absolute;cursor:pointer;"></div>');
            }
            if (poi.t) { // Second background marker
                for (var f = 0; f < poi.t.length; f++) {
                    j.push("<div class='hotspots' style=\"" + k + "left:" + poi.t[0] + "px;top:" + poi.t[1] + "px;width:" + poi.t[2] + "px;height:" + poi.t[3] + "px;");
                    if (AMap.Util.isIE && !AMap.Util.isIE9) {
                        j.push("background-color:#fff;cursor:hand;filter:alpha(opacity=1);");
                        if (10 === document.documentMode) { j.push("opacity:0.01;"); }
                    }
                    j.push('position:absolute;cursor:pointer;"></div>');
                }
            }

            if (!that.marker) that.addMarker();
            that.marker.setContent(j.join(""));
            that.marker.setPosition(new AMap.LngLat(poi.b[0], poi.b[3]));
            that.marker.show();
        },
        addMarker: function () {
            var that = this, mapObj = that.mapObj;
            if (that.marker) return;
            that.marker = new AMap.Marker({
                position: mapObj.getCenter(),
                zIndex: 99999,
                offset: new AMap.Pixel(0, 0),
                content: "",
                map: mapObj,
                visible: false
            });
            that.markerListener = AMap.event.addListener(that.marker, "click", that._handleMarkerClick, that);
        },
        _handleMarkerClick: function(evt){
            console.log("evt", evt);
            console.log("current POI:", this.lastPOI);
            
        },
        getNewTiles: function() {
            var that = this;
            var currentTiles = this.mapObj.getTiles();
            var newTiles = [];
            for (var i = 0; i < currentTiles.length; i++) {
                if (currentTiles[i] in that.hotspots) {
                    delete that.hotspots[currentTiles[i]]; //Remove old tile
                } else {
                    newTiles.push(currentTiles[i]);
                }
            }
            return newTiles;
        },
        addHotspot: function (poiResult) {
            if (!poiResult) return false;
            for (var h in poiResult.list) {
                this.hotspots[h] = poiResult.list[h];
            }
        },
        destroy: function () {
            this.disable();
            // Restore MapType plugin status
            if (this.mapTypeObj && this._needRenderMapType()) {
                this._fixMapTypeBug();
                var mapType = new AMap.MapType(this.mapTypeDefaultOptions);
                this.mapTypeObj = mapType;
                this.mapObj.addControl(mapType);// TODO
            }
            this.mapTypeDefaultOptions = {};
        },
        _fixMapTypeBug: function() {
            if (this.mapTypeObj.sublayers) {
                this.mapTypeObj.sublayers.road.layer.setMap(null);
                this.mapTypeObj.sublayers.traffic.layer.setMap(null);
            }
        },
        _needRenderMapType: function () {
            var mapTypeObj = this.mapTypeObj, mapTypeDefaultOptions = this.mapTypeDefaultOptions;
            return !(mapTypeObj.defaultType === mapTypeDefaultOptions.defaultType && mapTypeObj.showTraffic === mapTypeDefaultOptions.showTraffic && mapTypeObj.showRoad === mapTypeDefaultOptions.showRoad);
        },
        disable: function() {
            this._resetStatus();
            var listenerCount = this.eventListeners.length;
            if (listenerCount > 0) {
                for (var i = 0; i < listenerCount; i++) {
                    AMap.event.removeListener(this.eventListeners[i]);
                }
            }
        },
        enable: function () {
            this.initialize();
        }
    };
}